<?php
/**
 * | 节程 [ 节程赋能开发者，助力企业发展 ]
 * +----------------------------------------------------------------------
 *  | Copyright (c) 2020~2029 温州惊蛰网络科技有限公司 All rights reserved.
 * +----------------------------------------------------------------------
 *  | Licensed 节程并不是自由软件，未经许可不能去掉节程相关版权
 * +----------------------------------------------------------------------
 */
declare (strict_types=1);

namespace app\index\service;
use app\index\model\Collage;
use app\index\model\CollageItem;
use app\index\model\Configuration;
use app\index\model\GroupCommodity;
use app\index\model\IntegralRecord;
use app\index\model\MallBase;
use app\index\model\MembershipLevel;
use app\index\model\MembershipPresent;
use app\index\model\MembershipRecord;
use app\index\model\Order;
use app\index\model\OrderCommodity;
use app\index\model\RechargeRecord;
use app\index\model\User;
use app\index\model\UserCash;
use app\index\model\UserCoupon;
use app\index\model\ActivityRecharge;
use app\index\util\CreateNo;
use app\index\util\Inventory;
use app\index\util\Redis;
use app\index\model\PayMode;
use app\utils\Addons;
use app\utils\SendMsg;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
use think\db\Query;
use think\Exception;
use think\exception\InvalidArgumentException;
use think\facade\Cache;
use WeChat\Exceptions\InvalidResponseException;
use WeChat\Exceptions\LocalCacheException;
use WeChat\Pay;

class PaymentService
{

    private $user;

    private $redis;

    private $options;

    private $trade;

    private $msgData;

    private $baseIn;

    private $couponFlag = false;

    private $mallToken;

    public function __construct()
    {
        global $user;
        $this->user = User::find($user['id']);
        $this->redis = Redis::getInstance();

        $this->trade = CreateNo::buildOrderNo($this->user->id);


        //设置消息商城变量
        $this->msgData['mall_name'] = MallBase::getBase();
        $this->msgData['user_name'] = $this->user->nickname;
        $this->msgData['order_no'] = $this->trade;
        global $mallToken;
        $this->mallToken = $mallToken;
    }


    public function recharge(int $money)
    {
        $this->getOptions("wx");

        $rechargeMoney = bcdiv((string)$money, "100");

        $recordData = [
            "user_id" => $this->user->id,
            "base_in" => $this->baseIn,
            "source_type" => 1,
            "source" => "充值",
            "money" => $rechargeMoney,
            "trade" => $this->trade,
            'mall_id' => $this->user->mall_id
        ];


        $data = [
            'body' => "充值到账提醒",
            'total_fee' => $money,
            'notify_url' => request()->server("REQUEST_SCHEME") . '://' .
                $_SERVER['HTTP_HOST'] . "/index/notify/recharge",
            'goods_tag' => '充值成功',
        ];
        if ($this->baseIn == "web") {
            $jsapi = $this->getH5ForRecharge($data);
        } else {
            $jsapi = $this->getJsapiForRecharge($data);
        }

        $this->redis->lPush("RECHARGE:" . $this->trade, json_encode($recordData));
        $this->redis->expire("RECHARGE:" . $this->trade, 60 * 60);

        //TODO 商城变量整理
        $this->msgData['recharge_user'] = $this->user->nickname;
        $this->msgData['recharge_type'] = "微信支付";

        $this->msgData['recharge_reality_cash'] = $rechargeMoney;
        $this->msgData['recharge_time'] = time();


        Cache::set(checkRedisKey("MSGDATA:RECHARGE:" . $this->user->id), $this->msgData);

        return [HTTP_SUCCESS, $jsapi];
    }


    public function membershipWxpay(int $levelId)
    {
        $check = Addons::check($this->user->mall_id, 20);
        if (!$check)
            throw new Exception("请先激活插件", HTTP_NOTACCEPT);

        $levelModel = MembershipLevel::find($levelId);
        if (!$levelModel) {
            throw new Exception("会员等级不存在", HTTP_NOTACCEPT);
        }
        if ($levelModel->level <= $this->user->level) {
            throw new Exception("你的等级已经超过提交的等级", HTTP_NOTACCEPT);
        }
        if (empty($levelModel->is_buy_upgrade)) {
            throw new Exception("当前等级无法购买", HTTP_NOTACCEPT);
        }

        $this->getOptions("wx");

        $levelPrice = (int)bcmul((string)$levelModel->buy_price, "100",0);


        $data = [
            'body' => "充值到账提醒",
            'total_fee' => $levelPrice,
            'notify_url' => request()->server("REQUEST_SCHEME") . '://' .
                $_SERVER['HTTP_HOST'] . "/index/notify/membership",
            'goods_tag' => '充值成功',
        ];

        $trade = $this->trade;
        $record = [
            'mall_id' => $this->user->mall_id,
            'user_id' => $this->user->id,
            'base_in' => $this->baseIn,
            'source_type' => 3,
            'source' => '用户购买升级',
            'old_level' => $this->user->level ?: 0,
            'new_level' => $levelModel->level,
            'money' => $levelModel->buy_price,
            'trade' => $trade,
            'level_id' => $levelId
        ];

        $this->redis->lPush("MEMBERSHIP:" . $trade, json_encode($record));
        $this->redis->expire("MEMBERSHIP:" . $trade, 60 * 60);

        $jsapi = $this->getJsapi($data);
        return [HTTP_SUCCESS, $jsapi];
    }

    public function membershipBalance(int $levelId)
    {
        $check = Addons::check($this->user->mall_id, 20);
        if (!$check)
            throw new Exception("请先激活插件", HTTP_NOTACCEPT);

        $levelModel = MembershipLevel::find($levelId);
        if (!$levelModel)
            throw new Exception("会员等级不存在", HTTP_NOTACCEPT);
        if ($levelModel->level <= $this->user->level)
            throw new Exception("你的等级已经超过提交的等级", HTTP_NOTACCEPT);
        if (empty($levelModel->is_buy_upgrade))
            throw new Exception("当前等级无法购买", HTTP_NOTACCEPT);
        $levelPrice = $levelModel->buy_price;
        $userCash = UserCash::where('user_id', $this->user->id)->lock(true)->find();
        if ($userCash->total < $levelPrice) {
            throw new Exception('账户余额不足', HTTP_INVALID);
        }
        if ($levelPrice > 0) {
            UserCash::where('user_id', $this->user->id)->dec('total', (float)$levelPrice)->inc('expense', (float)$levelPrice)->update();
        }

        $recordData = [
            "user_id" => $this->user->id,
            "base_in" => $this->baseIn,
            'mall_id' => $this->user->mall_id,
            "source_type" => 0,
            "source" => "购买会员等级",
            "type" => 1,
            "money" => $levelPrice,
            "trade" => $this->trade,
            "old_cash" => $userCash->total,
            "new_cash" => bcsub((string)$userCash->total, (string)$levelPrice),
            "status" => 1
        ];
        RechargeRecord::create($recordData);

        $record = [
            'mall_id' => $this->user->mall_id,
            'user_id' => $this->user->id,
            'base_in' => $this->baseIn,
            'source_type' => 3,
            'source' => '用户购买升级',
            'old_level' => $this->user->level ?: 0,
            'new_level' => $levelModel->level,
            'money' => $levelModel->buy_price,
            'trade' => $this->trade,
            'level_id' => $levelId
        ];
        //变更会员等级
        $this->user->save([
            'level' => $levelModel->level,
            'level_time' => date('Y-m-d H:i:s',time() + (86400 * (int)$levelModel->indate))
        ]);

        //添加记录
        $membershipRecord = MembershipRecord::create($record);

        //下发奖励
        $membershipLevelList = MembershipLevel::where(
            [
                ['level', 'between', [$record['old_level'], $record['new_level']]],
                ['is_buy_upgrade', '=', 1]
            ])
            ->where(function (Query $query) {
                $query->whereOr([
                    ['is_present_money', '=', 1],
                    ['is_present_integer', '=', 1],
                    ['is_present_coupon', '=', 1],
                ]);
            })
            ->order('level', 'asc')
            ->select();

        if (!$membershipLevelList->isEmpty()) {
            $presentMoney = 0;
            $presentInteger = 0;
            $presentCoupon = [];

            //添加礼物记录
            foreach ($membershipLevelList as $k => $v) {
                $presentRecord = array();
                if (!empty($v['is_present_money'])) {
                    $presentRecord['present_money'] = $v['present_money'];
                    $presentMoney = bcadd((string)$presentMoney, (string)$v['present_money']);
                }
                if (!empty($v['is_present_integer'])) {
                    $presentRecord['present_integer'] = $v['present_integer'];
                    $presentInteger = bcadd((string)$presentInteger, (string)$v['present_integer']);
                }
                if (!empty($v['is_present_coupon'])) {
                    $couponIds = explode(',', $v['present_coupon']);
                    $couponList = \app\index\model\Coupon::where(['id' => $couponIds])
                        ->field('*')
                        ->select();
                    if (!$couponList->isEmpty()) {
                        $couponList->toArray();
                    }
                    $presentRecord['present_coupon'] = $couponList;
                    $presentCoupon = array_merge($presentCoupon, $couponIds);

                }
                $presentRecord['record_id'] = $membershipRecord->id;
                $presentRecord['level'] = $v->level;
                MembershipPresent::create($presentRecord);
            }

            //发放礼物
            if (!empty($presentMoney) || !empty($presentInteger)) {
                UserCash::where("user_id", $record['user_id'])
                    ->inc("recharge", (double)$presentMoney)
                    ->inc("total", (double)$presentMoney)
                    ->inc("integral", (double)$presentInteger)
                    ->inc("integral_total", (double)$presentInteger)
                    ->update();
                if(!empty($presentMoney)){
                    $this->giveAmount($presentMoney);
                }
                if(!empty($presentInteger)){
                    $this->giveIntegral($presentInteger);
                }
            }


            if (!empty($presentCoupon)) {
                $userCouponService = new UserCouponService();
                foreach ($presentCoupon as $couponId) {
                    try {
                        $userCouponService->save((int)$couponId);
                    } catch (DataNotFoundException $e) {
                    } catch (ModelNotFoundException $e) {
                    } catch (DbException $e) {
                    } catch (Exception $e) {
                    }
                }
            }
        }
        return [HTTP_SUCCESS, "购买成功"];
    }


    public function balance(array $orderList)
    {
        $this->getOptions("recharge");
        $money = $this->pickMoneyAndUnifiedOrderNo($orderList);

        if ($this->couponFlag) {
            $couponId = input("post.coupon");
            $orderCoupon = input("post.orderCoupon");
            $this->couponMoney($money, $orderList, $couponId, $orderCoupon);
        }
        $userCash = UserCash::where('user_id', $this->user->id)->lock(true)->find();
        if ($userCash->total < $money) {
            throw new Exception('账户余额不足', HTTP_INVALID);
        }
        if ($money > 0) {
            UserCash::where('user_id', $this->user->id)->dec('total', (float)$money)->inc('expense', (float)$money)->update();
        }

        $recordData = [
            "user_id" => $this->user->id,
            "base_in" => $this->baseIn,
            'mall_id' => $this->user->mall_id,
            "source_type" => 0,
            "source" => "消费",
            "type" => 1,
            "money" => $money,
            "trade" => $this->trade,
            "old_cash" => $userCash->total,
            "new_cash" => bcsub((string)$userCash->total, (string)$money),
            "status" => 1
        ];
        RechargeRecord::create($recordData);
        Order::where(['order_no' => $orderList])->update(['status' => 2, 'pay_time' => now(), 'pay_id' => 1, 'unified_order_no' => $this->trade, 'settlement' => 1]);
        $column = Order::where(['unified_order_no' => $this->trade])->column('id');
        Inventory::sub($column);
        OrderCommodity::update(['status' => 2], ['order_id' => $column]);
        foreach ($column as $key => $value)
            (new ReceiptsService)->printer($value, 'pay');

        // 拼团
        $oc = OrderCommodity::where(['order_id' => $column])->find();
        if ($oc['gc_id'] != 0) {
            Collage::createCollage($oc['id'], $this->user->id);
        }

        //设置消息商城变量

        global $mid;
        $check = Addons::check($mid, 4);
        \app\utils\Agent::upgrade($this->user);
        \app\utils\Agent::bindingPid($this->user);

        if ($check) {
            try {
                switch ($this->baseIn) {
                    case "wechata":
                        $this->msgData['thing4'] = "余额";
                        $this->msgData['amount2'] = $money;
                        $this->msgData['character_string1'] = $orderList[0];
                        $this->msgData['date3'] = date("Y-m-d H:i:s", time());
                        $url = url("/orderpage/order/list", ['tab' => 2, 'mall_id' => $mid], false, false)->build();
                        break;
                    case "wechat" || "web":
                        $this->msgData['pay_type'] = "余额";
                        $this->msgData['order_cash'] = $money;
                        $this->msgData['order_no'] = $orderList[0];
                        $url = url("/h5/#/orderpage/order/list", ['tab' => 2, 'mall_id' => $mid], false, true)->build();
                        break;
                    default:
                        $url = url("/h5/#/orderpage/order/list", ['tab' => 2, 'mall_id' => $mid], false, true)->build();
                }
                $sendMsg = new SendMsg("订单支付通知");
                $sendMsg->send($this->user, $this->msgData, $url);
                $sendMsg = new SendMsg("订单付款通知");
                $this->msgData['order_commodity'] = "余额下单";
                $this->msgData['buyer_name'] = $this->user->nickname;
                $this->msgData['buyer_mobile'] = $this->user->mobile;
                $this->msgData['order_no'] = $orderList[0];
                $sendMsg->send($this->user, $this->msgData, "");
            } catch (InvalidResponseException $e) {
            } catch (LocalCacheException $e) {
            } catch (Exception $e) {
            } catch (DataNotFoundException $e) {
            } catch (ModelNotFoundException $e) {
            } catch (DbException $e) {
            }
        }
        \app\index\util\Lottery::setUserLottery($this->user, $money);
        return [HTTP_SUCCESS, '下单成功'];
    }

    public function wxpay(array $orderList)
    {

        $this->getOptions("wx");
        $money = $this->pickMoneyAndUnifiedOrderNo($orderList);

        if ($this->couponFlag) {
            $couponId = input("post.coupon");
            $orderCoupon = input("post.orderCoupon");
            $this->couponMoney($money, $orderList, $couponId, $orderCoupon);
        }

        $money = intval(bcmul((string)$money, (string)100));

        if ($money > 0) {
            $data = [
                'body' => "您的商品下单成功",
                'total_fee' => $money,
                'notify_url' => request()->server("REQUEST_SCHEME") . '://' . $_SERVER['HTTP_HOST'] .
                    "/index/notify/commodity",
                'goods_tag' => '下单成功',
            ];
            if ($this->baseIn == "web") {
                $jsapi = $this->getH5($data, $orderList[0]);
            } else {
                $jsapi = $this->getJsapi($data);
            }

            $this->msgData['pay_type'] = "微信支付";
            Cache::set(checkRedisKey("MSGDATA:PAY:" . $this->user->id), $this->msgData);

            $this->redis->lPush("ORDER:" . $this->trade, 1);

            return [HTTP_SUCCESS, $jsapi];
        } else {

            Order::where(['order_no' => $orderList])->update(['status' => 2, 'unified_order_no' => $this->trade]);
            $column = Order::where(['unified_order_no' => $this->trade])->column('id');
            Inventory::sub($column);
            OrderCommodity::update(['status' => 2], ['order_id' => $column]);

            $this->msgData['pay_type'] = "微信支付";
            Cache::set(checkRedisKey("MSGDATA:PAY:" . $this->user->id), $this->msgData);
            return [HTTP_SUCCESS, "下单成功"];
        }

    }

    private function couponMoney(&$money, $orderList, $couponId, $orderCoupon)
    {
        if (!empty($couponId)) {
            $couponMoney = $this->coupon($couponId, $orderList, $money);
            $money = bcsub((string)$money, (string)$couponMoney);
        }
        if (!empty($orderCoupon)) {
            foreach ($orderCoupon as $k => $v) {
                if (!in_array($k, $orderList))
                    throw new InvalidArgumentException("优惠券不在提交的订单列表内", HTTP_FORBIDDEN);
                $orderCouponMoney = $this->orderCoupon($v, $k);
                $money = bcsub((string)$money, (string)$orderCouponMoney);
            }
        }
    }


    private function orderCoupon($id, $order)
    {
        $userCouponService = new UserCouponService();
        list($code, $model) = $userCouponService->read($id);
        if ($code != HTTP_SUCCESS)
            throw new Exception("优惠券不可用", HTTP_NOTACCEPT);
        if (!empty($model->used_type))
            throw new Exception("优惠券不可用", HTTP_NOTACCEPT);

        $orders = Order::where(['status' => 1, 'user_id' => $this->user->id, 'order_no' => $order])
            ->field('id,money,merchant_id')
            ->with(['orderCommodityHidden.commodityHidden'])
            ->find()->toArray();

        $money = $orders['money'];

        $commodityList = $this->getOrderCommodity($orders);

        if ($model->merchant_id != $orders['merchant_id']) {
            throw new Exception("优惠券不可用", HTTP_NOTACCEPT);
        }

        if ($model->coupon->conditions > $money) {
            throw new Exception("优惠券不可用", HTTP_NOTACCEPT);
        }

        if ($model->coupon->commodity_limit_type == 1) {
            $allowList = explode(",", $model->coupon->commodity_limit);
            $diffCommodity = array_intersect_key($commodityList, array_flip(array_diff(array_keys($commodityList), $allowList)));
            $diffMoney = 0;
            foreach ($diffCommodity as $i => $j) {
                bcadd((string)$diffMoney, bcmul((string)$j['count'], (string)$j['discount']));
            }
            $money = bcsub((string)$money, (string)$diffMoney);
            if ($money < $model->coupon->conditions) {
                throw new Exception("优惠券不可用", HTTP_NOTACCEPT);
            }
        } elseif ($model->coupon->commodity_limit_type == 2) {
            $allowList = explode(",", $model->coupon->commodity_limit);

            $diffCommodity = array_intersect_key($commodityList, array_flip(array_intersect(array_keys($commodityList), $allowList)));
            $diffMoney = 0;
            foreach ($diffCommodity as $i => $j) {
                bcadd((string)$diffMoney, bcmul((string)$j['count'], (string)$j['discount']));
            }
            $money = bcsub((string)$money, (string)$diffMoney);
            if ($money < $model->coupon->conditions) {
                throw new Exception("优惠券不可用", HTTP_NOTACCEPT);
            }
        } elseif ($model->coupon->commodity_limit_type == 3) {
            $allowList = explode(",", $model->coupon->commodity_limit);
            $allowList = array_map(function ($var) {
                return explode("->", $var);
            }, $allowList);
            $diffCommodity = [];
            foreach ($commodityList as $i => $j) {
                $explode = explode("->", $j['classify_id']);
                $flag = $this->arrayMatch($explode, $allowList);
                if (!$flag)
                    $diffCommodity[] = $j;
            }
            $diffMoney = 0;
            foreach ($diffCommodity as $i => $j) {
                bcadd((string)$diffMoney, bcmul((string)$j['count'], (string)$j['discount']));
            }
            $money = bcsub((string)$money, (string)$diffMoney);
            if ($money < $model->coupon->conditions) {
                throw new Exception("优惠券不可用", HTTP_NOTACCEPT);
            }
        }

        UserCoupon::update(["status" => 1, 'unified_order_no' => $order], ['id' => $id, 'status' => 0]);

        return $model->coupon->denomination;
    }


    private function coupon($id, $orderList, $money)
    {
        $userCouponService = new UserCouponService();
        list($code, $model) = $userCouponService->read($id);
        if ($code != HTTP_SUCCESS)
            throw new Exception("优惠券不可用", HTTP_NOTACCEPT);
        if ($model->merchant_id != 1 || !empty($model->used_type))
            throw new Exception("优惠券不可用", HTTP_NOTACCEPT);

        $orders = Order::where(['status' => 1, 'user_id' => $this->user->id, 'order_no' => $orderList])
            ->field('id,money')
            ->with(['orderCommodityHidden.commodityHidden'])
            ->select()->toArray();

        $commodityList = $this->getCommodity($orders);

        if ($model->coupon->conditions > $money) {
            throw new Exception("优惠券不可用", HTTP_NOTACCEPT);
        }

        if ($model->coupon->commodity_limit_type == 1) {
            $allowList = explode(",", $model->coupon->commodity_limit);
            $diffCommodity = array_intersect_key($commodityList, array_flip(array_diff(array_keys($commodityList), $allowList)));
            $diffMoney = 0;
            foreach ($diffCommodity as $i => $j) {
                bcadd((string)$diffMoney, bcmul((string)$j['count'], (string)$j['discount']));
            }
            $money = bcsub((string)$money, (string)$diffMoney);
            if ($money < $model->coupon->conditions) {
                throw new Exception("优惠券不可用", HTTP_NOTACCEPT);
            }
        } elseif ($model->coupon->commodity_limit_type == 2) {
            $allowList = explode(",", $model->coupon->commodity_limit);

            $diffCommodity = array_intersect_key($commodityList, array_flip(array_intersect(array_keys($commodityList), $allowList)));
            $diffMoney = 0;
            foreach ($diffCommodity as $i => $j) {
                bcadd((string)$diffMoney, bcmul((string)$j['count'], (string)$j['discount']));
            }
            $money = bcsub((string)$money, (string)$diffMoney);
            if ($money < $model->coupon->conditions) {
                throw new Exception("优惠券不可用", HTTP_NOTACCEPT);
            }
        } elseif ($model->coupon->commodity_limit_type == 3) {
            $allowList = explode(",", $model->coupon->commodity_limit);
            $allowList = array_map(function ($var) {
                return explode("->", $var);
            }, $allowList);
            $diffCommodity = [];
            foreach ($commodityList as $i => $j) {
                $explode = explode("->", $j['classify_id']);
                $flag = $this->arrayMatch($explode, $allowList);
                if (!$flag)
                    $diffCommodity[] = $j;
            }
            $diffMoney = 0;
            foreach ($diffCommodity as $i => $j) {
                bcadd((string)$diffMoney, bcmul((string)$j['count'], (string)$j['discount']));
            }
            $money = bcsub((string)$money, (string)$diffMoney);
            if ($money < $model->coupon->conditions) {
                throw new Exception("优惠券不可用", HTTP_NOTACCEPT);
            }
        }

        UserCoupon::update(["status" => 1, 'unified_order_no' => $this->trade], ['id' => $id, 'status' => 0]);

        return $model->coupon->denomination;
    }


    private function arrayMatch($explode, $allowList)
    {
        $flag = true;
        foreach ($allowList as $index => $item) {
            $diff = array_diff($item, $explode);
            if (empty($diff)) {
                $flag = false;
                break;
            }
        }
        return $flag;
    }


    private function getOrderCommodity(array $order)
    {
        $commodityList = [];
        foreach ($order['orderCommodityHidden'] as $i => $j) {
            $commodityList[$j['commodity_id']] = $j;
        }
        return $commodityList;
    }


    private function getCommodity(array $orders)
    {
        $commodityList = [];
        foreach ($orders as $k => $v) {
            foreach ($v['orderCommodityHidden'] as $i => $j) {
                $commodityList[$j['commodity_id']] = $j;
            }
        }
        return $commodityList;
    }



    private function pickMoneyAndUnifiedOrderNo(array $orderList)
    {
        $orderArray = Order::with(['freight'])
            ->lock(true)
            ->where('order_no', 'in', $orderList)
            ->where(['status' => 1, 'user_id' => $this->user->id])
            ->select();
        if (sizeof($orderArray) == 0)
            throw new Exception('订单不存在或已过期', HTTP_INVALID);
        $money = 0;
        $ftMoney = 0;
        $ft = false;
        $express = false;

        foreach ($orderArray as $v) {
            $money = bcadd((string)$money, (string)bcsub((string)bcsub((string)$v->money, (string)$v->discount), (string)$v->discount_amount));
            try {
                $ftMoney = bcadd((string)$ftMoney, $v->freight->freight);
            } catch (\Exception $e) {

            }
            if (!$ft) {
                if ($v->type == 1) {
                    $ft = true;
                }
            }
            if (!$express) {
                if ($v->type == 2) {
                    $express = $v->address;
                }
            }
        }
        $buyerAddress = '';
        if ($ft) {
            $buyerAddress .= "自提 + ";
        }
        if ($express) {
            $buyerAddress .= $express;
        }

        $realMoney = bcadd((string)$money, (string)$ftMoney);
        Order::update(
            ['unified_order_no' => $this->trade, 'unified_money' => $realMoney, "base_in" => $this->baseIn],
            ['status' => 1, 'user_id' => $this->user->id, 'order_no' => $orderList]
        );

        //设置消息商城变量
        $orderCommodity = OrderCommodity::with(['commodity'])->where(['order_id' => $orderArray[0]->id])->find();
        if(empty($orderCommodity->commodity))
            throw new Exception('商品不存在或者已经下架',HTTP_NOTACCEPT);
        $this->msgData['commodity_name'] = $orderCommodity->commodity->name . "...";
        $this->msgData['order_cash'] = $realMoney;
        $this->msgData['ft_price'] = $ftMoney;
        $this->msgData['buyer_name'] = $orderArray[0]->consignee;
        $this->msgData['buyer_mobile'] = $orderArray[0]->iphone;
        $this->msgData['buyer_address'] = $buyerAddress;
        $this->msgData['order_create_time'] = $orderArray[0]->create_time;

        return $realMoney;
    }


    private function getOptions($method)
    {
        global $baseIn;
        $this->baseIn = $baseIn;
        $configuration = Configuration::where(['type' => "mallPayMode"])->value("configuration");
        if (empty($configuration))
            throw new Exception("未完善支付配置", HTTP_NOTACCEPT);
        $configuration = json_decode($configuration, true);
        if (empty($configuration[$baseIn][$method])) {
            throw new Exception("未开启支付配置", HTTP_NOTACCEPT);
        }

        if (in_array($method, ['wx', 'ali'])) {

            $options = PayMode::find($configuration[$baseIn][$method . "_pay_mode_id"]);

            if (!$options) {
                throw new Exception("未配置支付模板", HTTP_NOTACCEPT);
            }

            $this->options = $options->toArray();

        }

    }

    private function getJsapi($orderData)
    {

        $baseData = [
            'out_trade_no' => $this->trade,
            $this->options['type']==2 ? 'sub_openid':'openid' => $this->user->userWx->openid,
            'attach' => $this->user->id,
            'trade_type' => 'JSAPI',
            'spbill_create_ip' => '127.0.0.1',
        ];

        $data = array_merge($baseData, $orderData);

        $arr = json_decode($this->options['configuration'], true);

        $jsapiOptions = [
            "appid" => $arr['AppId'],
            "mch_id" => $arr['MchId'],
            "mch_key" => $arr['APIKEY']
        ];
        if ($this->options['type']==2){
            $jsapiOptions['sub_appid']=$arr['M_AppId'] ?? '';
            $jsapiOptions['sub_mch_id']=$arr['M_MchId'] ?? '';
        }

        $pay = new Pay($jsapiOptions);
        $result = $pay->createOrder($data);

        if ($result['result_code'] !== "SUCCESS") {
            throw new Exception($result['err_code_des'], HTTP_NOTACCEPT);
        }
        $data=$pay->createParamsForJsApi($result['prepay_id']);
        $data['mode']=$this->options['mode'] ?? 0;
        return $data;
    }

    private function getH5($orderData, $order_no)
    {
        $baseData = [
            'out_trade_no' => $this->trade,
            'scene_info' => json_encode([
                'h5_info' => [
                    'type' => 'wap',
                    'wap_url' => request()->server("REQUEST_SCHEME") . '://' . $_SERVER['HTTP_HOST'],
                    'wap_name' => "惊蛰"
                ]
            ]),
            'trade_type' => 'MWEB',
            'spbill_create_ip' => $_SERVER['REMOTE_ADDR'],
        ];

        $data = array_merge($baseData, $orderData);
        $arr = json_decode($this->options['configuration'], true);
        $jsapiOptions = [
            "appid" => $arr['AppId'],
            "mch_id" => $arr['MchId'],
            "mch_key" => $arr['APIKEY']
        ];
        if ($this->options['type']==2){
            $jsapiOptions['sub_appid']=$arr['M_AppId'] ?? '';
            $jsapiOptions['sub_mch_id']=$arr['M_MchId'] ?? '';
        }
        
        $pay = new Pay($jsapiOptions);
        $result = $pay->createOrder($data);
        if ($result['result_code'] !== "SUCCESS") {
            throw new Exception($result['err_code_des'], HTTP_NOTACCEPT);
        }

        $host = request()->server("REQUEST_SCHEME") . '://' . $_SERVER['HTTP_HOST'];
        $ref = $host."/h5/wxispay.html?list=".$order_no."|total=".($orderData['total_fee']/100)."|mall_id=".$this->user->mall_id. "|pay";
        return $result['mweb_url']."&redirect_url=".$ref."&referer=".$host;
    }

    private function getJsapiForRecharge($orderData)
    {
        $baseData = [
            'out_trade_no' => $this->trade,
            'openid' => $this->user->userWx->openid,
//            'attach' => $id,
            'trade_type' => 'JSAPI',
            'spbill_create_ip' => '127.0.0.1',
        ];

        $data = array_merge($baseData, $orderData);
        $arr = json_decode($this->options['configuration'], true);
        $jsapiOptions = [
            "appid" => $arr['AppId'],
            "mch_id" => $arr['MchId'],
            "mch_key" => $arr['APIKEY']
        ];
        $pay = new Pay($jsapiOptions);
        $result = $pay->createOrder($data);
        if ($result['result_code'] !== "SUCCESS") {
            throw new Exception($result['err_code_des'], HTTP_NOTACCEPT);
        }
        return $pay->createParamsForJsApi($result['prepay_id']);
    }

    private function getH5ForRecharge($orderData)
    {
        $order_no = $this->trade;
        $baseData = [
            'out_trade_no' => $order_no,
            'scene_info' => json_encode([
                'h5_info' => [
                    'type' => 'wap',
                    'wap_url' => request()->server("REQUEST_SCHEME") . '://' . $_SERVER['HTTP_HOST'],
                    'wap_name' => "惊蛰"
                ]
            ]),
            'trade_type' => 'MWEB',
            'spbill_create_ip' => $_SERVER['REMOTE_ADDR'],
        ];

        $data = array_merge($baseData, $orderData);
        $arr = json_decode($this->options['configuration'], true);
        $jsapiOptions = [
            "appid" => $arr['AppId'],
            "mch_id" => $arr['MchId'],
            "mch_key" => $arr['APIKEY']
        ];
        $pay = new Pay($jsapiOptions);
        $result = $pay->createOrder($data);
        if ($result['result_code'] !== "SUCCESS") {
            throw new Exception($result['err_code_des'], HTTP_NOTACCEPT);
        }

        $host = request()->server("REQUEST_SCHEME") . '://' . $_SERVER['HTTP_HOST'];
        $ref = $host."/h5/wxispay.html?list=".$order_no."|total=".($orderData['total_fee']/100)."|mall_id=".$this->user->mall_id. "|recharge";
        return $result['mweb_url']."&redirect_url=".$ref."&referer=".$host;
    }


    private function getHashKey(array $data)
    {
        $str = "";
        foreach ($data as $k => $v) {
            if (!empty($v)) $str .= $k . ":" . $v . '-';
        }
        return trim($str, '-');
    }

    public function giveAmount($money){
        global $mid,$baseIn;
        $total = UserCash::where('user_id',$this->user->id)->value('total');
        RechargeRecord::create([
            'mall_id' => $mid,
            'user_id' => $this->user->id,
            'base_in' => $baseIn,
            'source_type' => 9,
            'source' => '开通会员等级',
            'is_online' => 0,
            'type' => 0,
            'card' => '{}',
            'money' => $money,
            'service_charge' => 0,
            'remark' => '开通会员等级获得'.$money,
            'trade' => '',
            'pay_no' => '',
            'status' => 1,
            'create_time' => date('Y-m-d H:i:s'),
            'update_time' => date('Y-m-d H:i:s'),
            'new_cash' => $total + $money,
            'old_cash' => $total
        ]);
    }
    public function giveIntegral($integral){
        global $mid,$baseIn;
        IntegralRecord::create([
            'mall_id' => $mid,
            'integral' => $integral,
            'type' => 12,
            'status' => 1,
            'number' => 0,
            'commodity_id' => 0,
            'sku_id' => 0,
            'order_id' => 0,
            'user_id' => $this->user->id,
            'create_time' => date('Y-m-d H:i:s'),
            'update_time' => date('Y-m-d H:i:s')
        ]);
    }


}
